#ifndef __SELECT_SERVER_HPP_
#define __SELECT_SERVER_HPP_

#include <iostream>
#include <sys/select.h>
#include "Socket.hpp"
#include <memory>
#include<unistd.h>


static const int _Size = sizeof(fd_set) * 8;

class SelectServer
{
private:
    void HandlerIO(fd_set *_pres)
    {

        for (int i = 0; i < _Size; i++)
        {
            if (fd_array[i] != -1)
            {
                if (FD_ISSET(fd_array[i], _pres))
                {
                    if(fd_array[i] == _listensockfd->SockFd())
                        Accepter();
                    else
                    {
                        Recver(fd_array[i]);
                    }
                }
               
            }
        }
    }

    void Accepter()
    {
        std::cout << "fd 准备就绪" << std::endl;

        Inet_Addr _Client;
        int _sockfd = _listensockfd->Accept(&_Client);
        for (int i = 0; i < _Size; i++)
        {
            if (fd_array[i] == -1)
            {
                fd_array[i] = _sockfd;
                break;
            }
        }
    }

    void Recver(int fd)
    {
        char buffer[1024];
        ssize_t n = recv(fd,buffer,sizeof(buffer) -1,0);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << buffer << std::endl;
        }
        else if(n == 0)
        {
            for(int i = 0;i<_Size;i++)
            {
                if(fd_array[i] == fd)
                {
                    fd_array[i] = -1;
                    break;
                }
                
            }
	    close(fd);
        }
        else
        {
            std::cout << "recv error" << std::endl;
            for(int i = 0;i<_Size;i++)
            {
                if(fd_array[i] == fd)
                {
                    fd_array[i] = -1;
                    break;
                }
                
            }
     
            close(fd);
        
   	    }
    }

public:
    SelectServer(int _port) : _listensockfd(std::make_unique<TcpSocket>())
    {
        _listensockfd->BulidSocket(_port);
        fd_array[0] = _listensockfd->SockFd();
    }

    void Run()
    {
        while (1)
        {
            fd_set _refds;
            FD_ZERO(&_refds);
            int _maxfd = -1;
            for (int i = 0; i < _Size; i++)
            {
                if (fd_array[i] != -1)
                {
                    FD_SET(fd_array[i], &_refds);
                    if (fd_array[i] > _maxfd)
                    {
                        _maxfd = fd_array[i];
                    }
                }
            }
            
            int n = select(_maxfd + 1, &_refds, nullptr, nullptr, nullptr);
            switch (n)
            {
            case 0:
                std::cout << "time out" << std::endl;
                break;
            case -1:
                perror("select");
                break;
            default:
                HandlerIO(&_refds);
                break;
            }
        }
    }

    ~SelectServer()
    {
    }

private:
    std::unique_ptr<Socket> _listensockfd;
    int fd_array[_Size] = {-1};
};

#endif
